package ssi.peeno.managers;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import org.bouncycastle.util.encoders.Base64;

public class KeyManager {
	private String keysDir;
	private String pwd;
	
	public KeyManager(String keysDir, String pwd) {
		this.keysDir = keysDir;
		this.pwd = pwd;
	}
	
	public PublicKey loadMyPublic() {
		return loadUserKey("Local");
	}

	public PrivateKey loadMyPrivate() {
		PrivateKey decoded = null;
		FileInputStream in = null;
		try {
			in = new FileInputStream(keysDir + "Local.private");
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		byte[] readedPrivate = new byte[1024];
		int inn; int i=0;
		try {
			while ((inn = in.read()) != -1) {
				readedPrivate[i] = (byte) inn;
				i++;
			}
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		try {
			in.close();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		byte[] decodedKey = Base64.decode(readedPrivate);
		KeyFactory keyFactory;
		try {
			keyFactory = KeyFactory.getInstance("RSA", "BC");
			EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(decodedKey);
			decoded = (PrivateKey) keyFactory.generatePrivate(privateKeySpec);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		}
		return decoded;
	}
	
	public String loadRawUserKey(String username) {
		BufferedReader in;
		try {
			in = new BufferedReader(new FileReader(keysDir + username + ".public"));
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
			return null;
		}
		try {
			String ret = "";
			String input = "";
			while ((input = in.readLine()) != null)
				ret += input;
			return ret;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}
	
	public PublicKey loadUserKey(String username) {
		PublicKey decoded = null;
		FileInputStream in = null;
		try {
			in = new FileInputStream(keysDir + username + ".public");
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		byte[] readedPublic = new byte[217];
		int inn; int i=0;
		try {
			while ((inn = in.read()) != -1) {
				readedPublic[i] = (byte) inn;
				i++;
			}
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		try {
			in.close();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		byte[] decodedKey = Base64.decode(readedPublic);
		KeyFactory keyFactory;
		try {
			keyFactory = KeyFactory.getInstance("RSA", "BC");
			EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(decodedKey);
			decoded= (PublicKey) keyFactory.generatePublic(publicKeySpec);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		}
		return decoded;
	}
	
	public void removeUserKey(String username) {
		File keyFile = new File(keysDir + username + ".public");
		if (keyFile.exists())
			keyFile.delete();
	}
	
	public void storeUserKey(String username, PublicKey key) {
		FileOutputStream os = null;
		try {
			os = new FileOutputStream(keysDir + username + ".public");
			os.write(Base64.encode(key.getEncoded()));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public void storeMyPrivate(Key privateKey) {
		FileOutputStream os = null;
		try {
			os = new FileOutputStream(keysDir + "Local" + ".private");
			os.write(Base64.encode(privateKey.getEncoded()));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void storeMyPublic(Key publicKey) {
		storeUserKey("Local", (PublicKey) publicKey);
	}

	
	/**
	 * Store private key for user in username.private
	 * @param username
	 * @param privateKey
	 */
	public void storePrivateKey(String username, String privateKey) {
		FileOutputStream os = null;
		try {
			os = new FileOutputStream(keysDir + username + ".private");
			os.write(privateKey.getBytes("UTF-8"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}

	public String loadPrivateKey(String username) {
		BufferedReader in;
		try {
			in = new BufferedReader(new FileReader(keysDir + username + ".private"));
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
			return null;
		}
		try {
			String ret = "";
			String input = "";
			while ((input = in.readLine()) != null)
				ret += input;
			return ret;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
		
	}
}
